package main.leetcode.clockin.June;

/**
 * 215. 数组中的第K个最大元素
 *
 * <p>在未排序的数组中找到第 k 个最大的元素。请注意，你需要找的是数组排序后的第 k 个最大的元素，而不是第 k 个不同的元素。
 *
 * <p>示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5
 *
 * <p>示例 2: 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
 *
 * <p>说明: 你可以假设 k 总是有效的，且 1 ≤ k ≤ 数组的长度。
 */
public class day29 {
    public static void main(String[] args) {
        System.out.println(new day29().findKthLargest(new int[] {3, 2, 1, 5, 6, 4}, 2));
        System.out.println(new day29().findKthLargest(new int[] {1, 2, 3, 4, 5, 6}, 1));
    }

    public int findKthLargest(int[] nums, int k) {
        int l = 0, r = nums.length - 1;
        int mid;
        k = nums.length - k;
        while (true) {
            mid = partition(nums, l, r);
            if (mid == k) {
                return nums[k];
            } else if (mid < k) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
    }

    private int partition(int[] nums, int l, int r) {
        int p = (int) (Math.random() * (r - l) + l);
        exch(nums, l, p);
        int pivot = nums[l];
        int i = l + 1, j = r;
        while (true) {
            while (i < r && nums[i] < pivot) {
                ++i;
            }
            while (j > l && nums[j] > pivot) {
                --j;
            }
            if (i >= j) {
                break;
            }
            exch(nums, i++, j--);
        }
        exch(nums, l, j);
        return j;
    }

    private void exch(int[] nums, int i, int j) {
        nums[i] = nums[i] + nums[j] - (nums[j] = nums[i]);
    }
}
